import os
import logging
import falcon
# import json
import WikiProcessor

logger = logging.getLogger(f"logger_main")
# base_dir = "."  # os.path.abspath(os.path.dirname(__file__)) + "/"
# logger.info(f"base_dir: {base_dir}")
wiki = WikiProcessor.WikiProcessor()


class PageHandler():
    def __init__(self):
        self.logger = logging.getLogger(f"logger_{__name__}")
        self.sink_slug = "/page/"

    def on_get(self, req, resp):
        # the part after the sink slug is the remaining url
        slug = req.relative_uri.split(self.sink_slug)[1]
        self.logger.info(f"accessing page: {slug}")
        resp.status = falcon.HTTP_200
        resp.content_type = "text/html"
        resp.body = wiki.get_page_by_name(slug)
        return


class IndexHandler():
    def __init__(self):
        self.logger = logging.getLogger(f"logger_{__name__}")

    def on_get(self, req, resp):
        self.logger.info("accessing index page")
        resp.status = falcon.HTTP_200
        resp.content_type = "text/html"
        resp.body = wiki.get_index_page()
        return


class StaticResource():
    def __init__(self):
        self.logger = logging.getLogger(f"logger_{__name__}")
        self.sink_slug = "/static/"

    def get_file_ending(self, url):
        return url.split("?")[0].split(".")[-1]

    def remove_query_params(self, url):
        return url.split("?")[0]

    def path_is_parent(self, parent_path, child_path):
        # Smooth out relative path names, note: If you are concerned
        # about symbolic links, you should use os.path.realpath too.
        parent_path = os.path.abspath(parent_path)
        child_path = os.path.abspath(child_path)
        common = os.path.commonpath([parent_path, child_path])
        # Compare the common path of the parent and child path with
        # the common path of just the parent path. Using the
        # commonpath method on just the parent path will regularise
        # the path name in the same way as the comparison that deals
        # with both paths, removing any trailing path separator
        return os.path.commonpath([parent_path]) == common

    def on_get(self, req, resp):
        # the part after the sink slug is the remaining url
        self.logger.info("uri: {}".format(req.relative_uri))
        self.logger.info("part after /static/: {}".format(
            req.relative_uri.split(self.sink_slug)[1]))
        part_after_static = req.relative_uri.split(self.sink_slug)[1]
        slug = os.path.join("static", self.remove_query_params(part_after_static))

        # security check
        assert self.path_is_parent("static", slug)

        self.logger.info(f"accessing static resource: {slug}")

        if self.path_is_parent("static", slug):
            if "." in req.relative_uri:
                file_format = self.get_file_ending(req.relative_uri)
                self.logger.info(f"file format is: {file_format}")

                if file_format == "css":
                    self.logger.info(f"serving a css file from {slug}")
                    resp.content_type = "text/css"
                    resp.status = falcon.HTTP_200
                    body = None
                    with open(slug, mode="r") as resource:
                        body = resource.read()
                    resp.body = body
                    return

                elif file_format in ["png", "jpg", "jpeg"]:
                    self.logger.info("serving an image file")
                    resp.content_type = "/".join(["image", file_format])
                    resp.status = falcon.HTTP_200
                    body = None
                    with open(slug, mode="rb") as resource:
                        body = resource.read()
                    resp.body = body
                    return

                elif file_format == "js":  # or file_format.split("?")[0] == "js":
                    self.logger.info("serving js file")
                    resp.content_type = "text/javascript"
                    resp.status = falcon.HTTP_200
                    body = None
                    with open(slug, mode="r") as resource:
                        body = resource.read()
                    resp.body = body
                    return

                else:
                    self.logger.info(f"trying to access unknown file format: {file_format}")
                    resp.status = falcon.HTTP_404
                    resp.content_type = "text/plain"
                    resp.body = "404"
                    return
            else:
                self.logger.info("Requested file has no file ending. "
                                 "Unsure how to return it.")
                resp.status = falcon.HTTP_404
                resp.content_type = "text/plain"
                resp.body = "404"
                return
        else:
            self.logger.info("Requested file not in static directory. "
                             "Permission to access supposedly static file denied.")
            resp.status = falcon.HTTP_403
            resp.content_type = "text/plain"
            resp.body = "403"
            return


class UnknownRouteHandler():
    def __init__(self):
        self.logger = logging.getLogger(f"logger_{__name__}")

    def on_get(self, req, resp):
        self.logger.info("accessing unknown route")
        resp.status = falcon.HTTP_404
        resp.content_type = "text/html"
        resp.body = "404"
        return


api = app = falcon.API()
api.add_route("/", IndexHandler())
api.add_sink(PageHandler().on_get, prefix="/page/")
api.add_sink(StaticResource().on_get, prefix="/static/")
# api.add_sink(UnknownRouteHandler().on_get, prefix="/")
